﻿//-----------------------------------------------------------------------
// <copyright file="Global.cs" company="INL sprl">
//     Copyright 2009-2010 INL sprl.
// </copyright>
//-----------------------------------------------------------------------

namespace ParseXAML
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;

    /// <summary>
    /// Classe prévue pour contenir les paramètres globaux de l'application
    /// </summary>
    /// <remarks>
    /// Parse la ligne de commande.
    /// Permet de charger les propriétés qui doivent être analyser.
    /// Permet d'obtenir la liste des fichiers à analyser.
    /// </remarks>
    public class Global
    {
        public bool GenerateWrapperClassForResource = true;

        public string StandardResxGenerator = "PublicResXFileCodeGenerator";

        public string PublicResXGenerator = "PublicResourceCodeGenerator";

        public string DefaultStringBinding = "{Binding %Name%, Source={StaticResource %ResourceName%}}";
        ////{lex:LocText %AssemblyName%:%ResourceFullNameWithOutGlobal%:%Name%}

        /// <summary>
        /// Indique si on génére un fichier translat ou si on fait un fichier translat.cs
        /// </summary>
        public bool IsGenerateCodeBehind = false;

        /// <summary>
        /// If an element has content, try to convert to attribute Content=
        /// </summary>
        public bool TryToConvertElementToContent = true;

        /// <summary>
        /// Allow to create Name Attribute on second pass
        /// </summary>
        public bool CreateNameAttribute = false;

        /// <summary>
        /// Allow to create Uid Attribute on second pass
        /// </summary>
        public bool CreateUidAttribute = false;

        /// <summary>
        /// If value change in XAML file => update the resX file or leave unchanged
        /// </summary>
        public bool UpdateResX = true;

        /// <summary>
        /// Ignore strings begin with (multiple prefix, separated by ; 
        /// </summary>
        public string IgnoreStringBeginBy;

        /// <summary>
        /// The binding string
        /// </summary>
        public string BindingString;

        /// <summary>
        /// Allow to create Uid Attribute on second pass
        /// </summary>
        public bool IsSilverlight = true;

        /// <summary>
        /// Element with Content will be converted to Text Attribute
        /// </summary>
        public List<string> ElementContentToText = new List<string>() { "System.Windows.Controls.TextBlock" };

        /// <summary>
        /// Element with Content will be converted to Text Attribute
        /// </summary>
        public List<string> ElementContentToContent = new List<string>() 
        { 
            "System.Windows.Controls.Label", 
            "System.Windows.Controls.ComboBoxItem",
            "System.Windows.Controls.CheckBox",
            "System.Windows.Controls.RadioButton"
        };

        private LocalizableControls localizableControls = null;

#if ANALYSE_ASSEMBLY
        /// <summary>
        /// Full path where DLL are created
        /// </summary>
        public string FullOutputPath { get; set; }

        internal LocalizableAssembly _LocalizableAssembly = null;

        internal LocalizableAssembly LocalizableAssembly
        {
            get
            {
                if (this._LocalizableAssembly == null)
                    this._LocalizableAssembly = new LocalizableAssembly(this, References);
                return this._LocalizableAssembly;
            }
        }

        public List<Reference> References = new List<Reference>();
#endif

        /// <summary>
        /// Nom du fichier externe qui contient la liste des membres à analyser
        /// </summary>
        private string localizableControlsFileName;

        /// <summary>
        /// Initializes a new instance of the Global class.
        /// </summary>
        public Global()
        {
            this.LocalizableControlsAndProperties = BaseIO<LocalizablePropertiesFromXML>.ReadFromStream(System.Reflection.Assembly.GetExecutingAssembly().GetManifestResourceStream("ParseXAML.properties.xml"));
        }

        /// <summary>
        /// Delegate pour les messages internes
        /// </summary>
        /// <param name="sender">Instance de l'envoyeur</param>
        /// <param name="fe">Message envoyé</param>
        public delegate void MessageEventHandler(object sender, MessageEventArgs fe);

        /// <summary>
        /// Delegate pour le log des messages
        /// </summary>
        /// <param name="sender">Instance de l'envoyeur</param>
        /// <param name="fe">Message envoyé</param>
        public delegate void LogMessageEventHandler(object sender, LogMessageEventArgs fe);

        /// <summary>
        /// Appelé pour les messages internes générés par l'application
        /// </summary>
        public event MessageEventHandler OnMessage;

        /// <summary>
        /// Appelé pour les différentes adaptations faites aux fichiers
        /// </summary>
        public event LogMessageEventHandler OnLogMessage;

        /// <summary>
        /// Gets or sets le répertoire dans lequel on cherche les fichiers XAML
        /// </summary>
        public string Folderpath { get; set; }

        /// <summary>
        /// Gets or sets les propriétés qui doivent être analyser dans les fichiers XAML
        /// </summary>
        public LocalizablePropertiesFromXML LocalizableControlsAndProperties { get; set; }

        /// <summary>
        /// Gets or sets the namespace for resource.
        /// </summary>
        public string ResourceNamespace2 { get; set; }

        /// <summary>
        /// The name of the assembly
        /// </summary>
        public string TargetAssemblyName { get; set; }

        /// <summary>
        /// Gets or sets the default namespace.
        /// </summary>
        public string DefaultNamespace { get; set; }

        internal LocalizableControls LocalizableControls
        {
            get
            {
                if (this.localizableControls == null)
                {
#if ANALYSE_ASSEMBLY
                    this._LocalizableControls = new LocalizableControls(this, this.LocalizableAssembly);
#else
                    this.localizableControls = new LocalizableControls(this, null);
#endif
                }

                return this.localizableControls;
            }
        }

        /// <summary>
        /// Traite les arguments de la ligne de commande
        /// </summary>
        /// <param name="args">Arguments de la ligne de commande.</param>
        /// <returns>Indique si on peut continuer ou s'il faut arrêter l'éxécution</returns>
        public bool Go(string[] args)
        {
            if (args == null)
            {
                return ShowUsage();
            }

            for (int i = 0; i < args.Length; i++)
            {
                switch (args[i])
                {
                    case "-p":
                        i++;
                        if (i < args.Length)
                        {
                            this.Folderpath = args[i];
                        }

                        break;
                    case "-nr":
                        i++;
                        if (i < args.Length)
                        {
                            this.DefaultNamespace = args[i];
                            this.ResourceNamespace2 = args[i];
                        }

                        break;
                    case "-ie":
                        i++;
                        if (i < args.Length)
                        {
                            this.localizableControlsFileName = args[i];
                        }

                        break;
                    case "-rg":
                        i++;
                        if (i < args.Length)
                        {
                            this.PublicResXGenerator = args[i];
                        }

                        break;
                }
            }

            if (string.IsNullOrEmpty(this.Folderpath))
            {
                return ShowUsage();
            }

            if (!string.IsNullOrEmpty(this.localizableControlsFileName))
            {
                this.LocalizableControlsAndProperties = BaseIO<LocalizablePropertiesFromXML>.ReadFromFile(this.localizableControlsFileName);
            }

            // LocalizableControls = new LocalizableControls();
            // LocalizableControls.includeProperties.Add(string.Empty, new LocalizableControl("Text","Content"));
            // LocalizableControls.includeProperties.Add("Nununuche.Taratata.com", new LocalizableControl("PasTouche"));
            // LocalizableControls.excludeProperties.Add("Nununuche.Taratata.com", new LocalizableControl("Text"));
            // LocalizableControls.SaveToFile("c:\\properties.xml");
            return true;
        }

        /// <summary>
        /// Récupère la liste de tous les fichiers à analyser
        /// </summary>
        /// <returns>Renvoie une liste de fichiers avec leur nom complet</returns>
        public List<string> GetFiles()
        {
            List<string> res = new List<string>();
            if (System.IO.File.Exists(this.Folderpath))
            {
                res.Add(this.Folderpath);
            }

            if (System.IO.Directory.Exists(this.Folderpath))
            {
                res.AddRange(GetFilesFromDir(new System.IO.DirectoryInfo(this.Folderpath)));
            }

            return res;
        }

        /// <summary>
        /// Add a message
        /// </summary>
        /// <param name="message">The message to add</param>
        public void AddMessage(Message message)
        {
            MessageEventArgs evt = new MessageEventArgs(message);
            if (this.OnMessage != null)
            {
                this.OnMessage(this, evt);
            }
        }

        /// <summary>
        /// Add a message
        /// </summary>
        /// <param name="type">Type of message</param>
        /// <param name="message">Content of message parametrized (xx {0} yy)</param>
        /// <param name="param">Paramètres à appliquer</param>
        public void AddMessage(Message.eType type, string message, params object[] param)
        {
            this.AddMessage(new Message(type, string.Format(message, param)));
        }

        /// <summary>
        /// Add a log message
        /// </summary>
        /// <param name="type">Type of message</param>
        /// <param name="message">Content of message parametrized (xx {0} yy)</param>
        /// <param name="param">Paramètres à appliquer</param>
        public void AddLogMessage(LogMessage.eType type, string message, params object[] param)
        {
            LogMessageEventArgs evt = new LogMessageEventArgs(new LogMessage(type, string.Format(message, param)));
            if (this.OnLogMessage != null)
            {
                this.OnLogMessage(this, evt);
            }
        }

        /// <summary>
        /// Applique les paramètres aux paramètres globaux
        /// </summary>
        /// <param name="myParams">Paramètres à appliquer</param>
        public void MergeParams(Params myParams)
        {
            this.IsGenerateCodeBehind = myParams.Method == Params.eMethod.Code;
            if (myParams.IncludeProperties != null)
            {
                this.LocalizableControlsAndProperties.IncludeProperties = myParams.IncludeProperties;
            }

            if (myParams.ExcludeProperties != null)
            {
                this.LocalizableControlsAndProperties.ExcludeProperties = myParams.ExcludeProperties;
            }

            this.GenerateWrapperClassForResource = myParams.GenerateWrapperClassForResource;
            this.PublicResXGenerator = myParams.ResXGenerator;
            this.TryToConvertElementToContent = myParams.TryToConvertElementToContent;
            this.UpdateResX = myParams.UpdateResX;
            this.IgnoreStringBeginBy = myParams.IgnoreStringBeginBy;
            this.BindingString = myParams.BindingString;
        }

        /// <summary>
        /// Récupère la liste des fichiers à traiter, à partir d'un répertoire et ceci de façon récursive
        /// </summary>
        /// <param name="directoryInfo">Répertoire à analyser</param>
        /// <returns>Renvoie une liste de fichiers avec leur nom complet</returns>
        private static List<string> GetFilesFromDir(System.IO.DirectoryInfo directoryInfo)
        {
            System.IO.FileInfo[] xamlFiles = directoryInfo.GetFiles("*.xaml");
            List<string> res = new List<string>();
            foreach (System.IO.FileInfo fi in xamlFiles)
            {
                res.Add(fi.FullName);
            }

            foreach (System.IO.DirectoryInfo di in directoryInfo.GetDirectories())
            {
                res.AddRange(GetFilesFromDir(di));
            }

            return res;
        }

        /// <summary>
        /// Affiche comment utiliser le programme
        /// </summary>
        /// <returns>Renvoie toujours faux.</returns>
        private static bool ShowUsage()
        {
            Console.WriteLine("GenerateXAML -p <path to folder project> [-nr <namespace for resource>] [-ie <xml file with properties to scan>] [-rg <resource generator (resx=>designer)>]");
            return false;
        }
    }
}
